﻿/*
 * This class provides the methods to interact with the configuration database created in sql compact edition.
 * <para>Entity model framework is used to generate the database entities.
 * <para>The database structure can be seen by opening the Configuration.edmx file in this project.
 */

using System;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Collections.Generic;
using Valentia.Kinection.DataTypes;
using Valentia.Kinection.Configuration;

namespace Valentia.Kinection.Configuration
{
    /// <summary>
    /// Configuration helper class.
    /// <para>This class provides the methods to interact with the configuration database created in sql compact edition.</para>
    /// <para>Entity model framework is used to generate the database entities.</para>
    /// <para>The database structure can be seen by opening the Configuration.edmx file in this project.</para>
    /// </summary>
    public static class ConfigurationHelper
    {
        #region DATA MEMBERS
        /// <summary>
        ///  Objects that already exist in the object context are not loaded from the data source.
        /// </summary>
        private static MergeOption executeMergeOption = MergeOption.AppendOnly;

        /// <summary>
        /// Database connection string.
        /// </summary>
        private static String connectionString =
            @"metadata=res://*/Configuration.csdl|res://*/Configuration.ssdl|res://*/Configuration.msl;provider=System.Data.SqlServerCe.3.5;" +
            @"provider connection string=""Data Source=|DataDirectory|\ConfigDatabase.sdf"";";
        #endregion

        #region STATIC CONSTRUCTOR
        /// <summary>
        /// Static constructor.
        /// </summary>
        static ConfigurationHelper()
        {
            #region Saving values of notification IDs in Notification table if not already exists.

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {

                ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value n from Notifications as n Where n.NotificationID = @NotificationID", new ObjectParameter("NotificationID", typeof(int)));

                foreach (String notificationType in Enum.GetNames(typeof(NotificationType)))
                {
                    int notificationTypeInt = (int)((NotificationType)(Enum.Parse(typeof(NotificationType), notificationType, true)));
                    query.Parameters["NotificationID"].Value = notificationTypeInt;

                    if (query.Execute(ConfigurationHelper.executeMergeOption).Count() > 0) continue;

                    Notification notif = new Notification();
                    notif.NotificationID = notificationTypeInt;
                    context.Notifications.AddObject(notif);
                }

                context.SaveChanges();
            }

            #endregion

            #region Saving values of skeleton joints IDs in SkeletonJoint table if not already exists.

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value n from SkeletonJoints as n Where n.JointID = @JointID", new ObjectParameter("JointID", 1));

                foreach (String skeletonJoint in Enum.GetNames(typeof(SkeletonJointID)))
                {
                    int skeletonJointInt
                        = (int)((SkeletonJointID)(Enum.Parse(typeof(SkeletonJointID)
                        , skeletonJoint, true)));

                    query.Parameters["JointID"].Value = skeletonJointInt;

                    if (query.Execute(ConfigurationHelper.executeMergeOption).Count() > 0) continue;

                    SkeletonJoint skelJoint = new SkeletonJoint();
                    skelJoint.JointID = skeletonJointInt;
                    context.SkeletonJoints.AddObject(skelJoint);
                }

                context.SaveChanges();
            }

            #endregion
        }
        #endregion

        #region METHODS
        /// <summary>
        /// Used to get context for querying and working with entity objects.
        /// </summary>
        /// <returns>ConfigDatabaseEntities.</returns>
        public static ConfigDatabaseEntities GetContext()
        {
            return new ConfigDatabaseEntities(ConfigurationHelper.connectionString);
        }

        #region KINECT DEVICE RELATED METHODS
        /// <summary>
        /// Gets all the registered kinect devices.
        /// </summary>
        /// <returns>list of kinect devices.</returns>
        public static List<KinectDevice> GetAllKinectDevices()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<KinectDevice> query = context.CreateQuery<KinectDevice>("Select value p from KinectDevices as p");
                ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the kinect device by the name.
        /// </summary>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Kinect device if found else will return null.</returns>
        public static KinectDevice GetKinectDeviceByName(String kinectDeviceName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetKinectDeviceByName(context, kinectDeviceName);
            }
        }

        /// <summary>
        /// Gets the kinect device by the name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Kinect device if found else will return null.</returns>
        public static KinectDevice GetKinectDeviceByName(ConfigDatabaseEntities context, String kinectDeviceName)
        {
            ObjectQuery<KinectDevice> query =
                    context.CreateQuery<KinectDevice>(
                    "Select value p from KinectDevices as p Where p.KinectDeviceName = @KinectDeviceName", new ObjectParameter("KinectDeviceName", kinectDeviceName));
            ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (KinectDevice kinectDevice in results) { return kinectDevice; }

            return null;
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="kinectDeviceID">Kinect device ID.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(String kinectDeviceID, String kinectDeviceName)
        {
            //The kinect device is saved with the default values for smoothing parameters, resoloutions and image type. All the bits values for active,
            //Color image, depth image and skeleton image are enabled
            return ConfigurationHelper.SaveKinectDevice(
                kinectDeviceID, kinectDeviceName, true, true, true, true, 0.5f, 0.5f, 0.5f, 0.05f, 0.04f, KinectColorImageFormat.RgbResolution640x480Fps30,
                KinectDepthImageFormat.Resolution320x240Fps30);
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="kinectDeviceID">Kinect device ID.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <param name="active">True if device to be active else false.</param>
        /// <param name="kinectRuntimeOptions">Run time initialization options.</param>
        /// <param name="generateVideoStream">True to generate video stream else false.</param>
        /// <param name="generateDepthStream">True to depth video stream else false.</param>
        /// <param name="generateSkeletonStream">True to skeleton video stream else false.</param>
        /// <param name="skeletonSmoothing">
        /// Skeleton Smoothing parameter.
        /// <para>The amount of smoothing, ranging from 0.0 (no smoothing) to 1.0 (full smoothing). The default value is 0.5</para>
        /// </param>
        /// <param name="skeletonCorrection">
        /// Skeleton Correction parameter.
        /// <para>The amount of correction, ranging from 0.0 (no correction) to 1.0 (full correction). The default value is 0.5.</para>
        /// </param>
        /// <param name="skeletonPrediction">Skeleton Prediction parameter.</param>
        /// <param name="skeletonJitterRadius">
        /// Skeleton JitterRadius parameter.
        /// <para>The jitter-reduction radius (in meters). The default value is 0.05 (5 cm). Any jitter less than this radius is aggressively smoothed out.</para>
        /// </param>
        /// <param name="skeletonMaxDeviationRadius">
        /// Skeleton smoothing parameter.
        /// <para>The maximum radius (in meters) that filtered positions can deviate from raw data. The default value is 0.04.</para>
        /// </param>
        /// <param name="colorResoloution">Video resoloution.</param>
        /// <param name="depthResoloution">Depth resoloution.</param>
        /// <param name="skeletonResoloution">Skeleton resoloution.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(
            String kinectDeviceID, String kinectDeviceName, bool active, bool generateVideoStream, bool generateDepthStream,
            bool generateSkeletonStream, double skeletonSmoothing, double skeletonCorrection, double skeletonPrediction, double skeletonJitterRadius,
            double skeletonMaxDeviationRadius, KinectColorImageFormat colorResoloution, KinectDepthImageFormat depthResoloution)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveKinectDevice(context, new KinectDevice()
                {
                    KinectDeviceID = kinectDeviceID,
                    KinectDeviceName = kinectDeviceName,
                    Active = active,
                    RuntimeInitializationOptions = 0,
                    GenerateVideoStream = generateVideoStream,
                    GenerateDepthStream = generateDepthStream,
                    GenerateSkeletonStream = generateSkeletonStream,
                    SkeletonSmoothing = skeletonSmoothing,
                    SkeletonCorrection = skeletonCorrection,
                    SkeletonPrediction = skeletonPrediction,
                    SkeletonJitterRadius = skeletonJitterRadius,
                    SkeletonMaxDeviationRadius = skeletonMaxDeviationRadius,
                    ID = context.KinectDevices.NextId(f => f.ID),
                    KinectVideoResoloution = colorResoloution,
                    KinectDepthResoloution = depthResoloution,
                    SkeletonResoloution = 0,
                    VideoImageType = 0,
                    DepthImageType = 0,
                });
            }
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="kinectDevice">Kinect device to save.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(ConfigDatabaseEntities context, KinectDevice kinectDevice)
        {
            return context.KinectDevices.AddAndSaveChanges(context, kinectDevice);
        }

        /// <summary>
        /// Deletes kinect device from database using device name.
        /// </summary>
        /// <param name="kinectDeviceName">Device name to be used.</param>
        /// <returns>True if kinect device deleted successfuly else False.</returns>
        public static bool DeleteKinectDeviceByName(String kinectDeviceName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteKinectDeviceByName(context, kinectDeviceName))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Deletes kinect device from database using device name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>True if kinect device deleted successfuly else False.</returns>
        public static bool DeleteKinectDeviceByName(ConfigDatabaseEntities context, String kinectDeviceName)
        {
            ObjectQuery<KinectDevice> query =
                    context.CreateQuery<KinectDevice>(
                    "Select value p from KinectDevices as p Where p.KinectDeviceName = @KinectDeviceName", new ObjectParameter("KinectDeviceName", kinectDeviceName));
            ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (KinectDevice kinectDevice in results)
            {
                context.KinectDevices.DeleteObject(kinectDevice);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Deletes all the registered kinect devices.
        /// </summary>
        /// <returns>True if all kinect devices deleted successfuly else False.</returns>
        public static bool DeleteAllKinectDevices()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<KinectDevice> query = context.CreateQuery<KinectDevice>("Select value p from KinectDevices as p");
                ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (KinectDevice kinectDevice in results)
                {
                    context.KinectDevices.DeleteObject(kinectDevice);
                }

                context.SaveChanges();

                return true;
            }
        }
        #endregion

        #region DATA USER RELATED METHODS
        /// <summary>
        /// Gets all service clients.
        /// </summary>
        /// <returns>List of service clients.</returns>
        public static List<DataUser> GetAllDataUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<DataUser> query = context.CreateQuery<DataUser>("Select value p from DataUsers as p");
                ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the service client by the login name.
        /// </summary>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>Service client if found else will return null.</returns>
        public static DataUser GetDataUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetDataUserByLoginName(context, loginName);
            }
        }

        /// <summary>
        /// Gets the service client by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>Service client if found else will return null.</returns>
        public static DataUser GetDataUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<DataUser> query =
                    context.CreateQuery<DataUser>(
                    "Select value p from DataUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));
            ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUser dataUser in results) { return dataUser; }

            return null;

        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="name">Service client name.</param>
        /// <param name="login">Service client login name.</param>
        /// <param name="password">Service client password.</param>
        /// <returns>Saved service client object.</returns>
        public static DataUser SaveDataUser(String name, String login, String password)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUser(context, new DataUser()
                {
                    ID = context.DataUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = true,
                    SendVideoFrame = true,
                    SendDepthFrame = true,
                    SendSkeletonFrame = true,
                });
            }
        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="name">Service client name.</param>
        /// <param name="login">Service client login name.</param>
        /// <param name="password">Service client password.</param>
        /// <param name="active">Service client is active.</param>
        /// <param name="sendVideoFrame">Service client can recieve video frame.</param>
        /// <param name="sendDepthFrame">Service client can recieve depth frame.</param>
        /// <param name="sendSkeletonFrame">Service client can recieve skeleton frame.</param>
        /// <returns>Saved service client object.</returns>
        public static DataUser SaveDataUser(String name, String login, String password, bool active, bool sendVideoFrame, bool sendDepthFrame, bool sendSkeletonFrame)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUser(context, new DataUser()
                {
                    ID = context.DataUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = active,
                    SendVideoFrame = sendVideoFrame,
                    SendDepthFrame = sendDepthFrame,
                    SendSkeletonFrame = sendSkeletonFrame,
                });
            }
        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUser">Saved service client object.</param>
        public static DataUser SaveDataUser(ConfigDatabaseEntities context, DataUser dataUser)
        {
            return context.DataUsers.AddAndSaveChanges(context, dataUser);
        }

        /// <summary>
        /// Delete service client by login name
        /// </summary>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>True if user deleted successfully else False.</returns>
        public static bool DeleteDataUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteDataUserByLoginName(context, loginName))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Delete service client by login name
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>True if user deleted successfully else False.</returns>
        public static bool DeleteDataUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<DataUser> query =
                    context.CreateQuery<DataUser>(
                    "Select value p from DataUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));
            ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUser dataUser in results)
            {
                context.DataUsers.DeleteObject(dataUser);
                return true;
            }

            return false;

        }

        /// <summary>
        /// Delete all Service clients
        /// </summary>
        /// <returns>True if all users deleted successfully else False</returns>
        public static bool DeleteAllDataUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<DataUser> query = context.CreateQuery<DataUser>("Select value p from DataUsers as p");
                ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (DataUser dataUser in results)
                {
                    context.DataUsers.DeleteObject(dataUser);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #region UTILITY USER RELATED METHODS
        /// <summary>
        /// Gets all the utility users.
        /// </summary>
        /// <returns>List of utility users.</returns>
        public static List<UtilityUser> GetAllUtilityUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUser> query = context.CreateQuery<UtilityUser>("Select value p from UtilityUsers as p");
                ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the Utility user by the login name.
        /// </summary>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>Utility user if found else will return null.</returns>
        public static UtilityUser GetUtilitiyUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetUtilitiyUserByLoginName(context, loginName);
            }
        }

        /// <summary>
        /// Gets the Utility user by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>Utility user instance if found else will return null.</returns>
        public static UtilityUser GetUtilitiyUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<UtilityUser> query =
                    context.CreateQuery<UtilityUser>(
                    "Select value p from UtilityUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));

            ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUser utilityUser in results) { return utilityUser; }

            return null;
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="name">Utility user name.</param>
        /// <param name="login">Utility user login name.</param>
        /// <param name="password">Utility user password.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(String name, String login, String password)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUser(context, new UtilityUser()
                {
                    ID = context.UtilityUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = true,
                });
            }
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="name">Utility user name.</param>
        /// <param name="login">Utility user login name.</param>
        /// <param name="password">Utility user password.</param>
        /// <param name="active">Is Active.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(String name, String login, String password, bool active)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUser(context, new UtilityUser()
                {
                    ID = context.UtilityUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = active,
                });
            }
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUser">Utility user to save.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(ConfigDatabaseEntities context, UtilityUser utilityUser)
        {
            return context.UtilityUsers.AddAndSaveChanges(context, utilityUser);
        }

        /// <summary>
        /// Deletes the Utility user by the login name.
        /// </summary>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>True if utility user deleted successfully else false.</returns>
        public static bool DeleteUtilitiyUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteUtilitiyUserByLoginName(context, loginName))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes the Utility user by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>True if utility user deleted successfully else false.</returns>
        public static bool DeleteUtilitiyUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<UtilityUser> query =
                    context.CreateQuery<UtilityUser>(
                    "Select value p from UtilityUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));

            ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUser utilityUser in results)
            {
                context.UtilityUsers.DeleteObject(utilityUser);

                return true;
            }

            return false;
        }

        /// <summary>
        /// Deletes all the utility users from application database.
        /// </summary>
        /// <returns>True if all utility user deleted successfully else false.</returns>
        public static bool DeleteAllUtilityUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUser> query = context.CreateQuery<UtilityUser>("Select value p from UtilityUsers as p");
                ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (UtilityUser utilityUser in results)
                {
                    context.UtilityUsers.DeleteObject(utilityUser);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #region NOTIFICATION RELATED METHODS
        /// <summary>
        /// Gets the Notification by the notification id.
        /// </summary>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>Notification if found else will return null.</returns>
        public static Notification GetNotificationByID(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetNotificationByID(context, notificationID);
            }
        }

        /// <summary>
        /// Gets the Notification by the notification id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>Notification if found else will return null.</returns>
        public static Notification GetNotificationByID(ConfigDatabaseEntities context, int notificationID)
        {
            ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value p from Notifications as p Where p.NotificationID = @NotificationID"
                    , new ObjectParameter("NotificationID", notificationID));

            ObjectResult<Notification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (Notification notification in results) { return notification; }

            return null;
        }

        /// <summary>
        /// Saves the Notification to application database.
        /// </summary>
        /// <param name="notificationID">Notification ID.</param>
        /// <returns>Saved notification object.</returns>
        public static Notification SaveNotification(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveNotification(context, new Notification()
                {
                    NotificationID = notificationID
                });
            }
        }

        /// <summary>
        /// Saves the notification to application database.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="notification">Notification to save.</param>
        /// <returns>Saved notification object.</returns>
        public static Notification SaveNotification(ConfigDatabaseEntities context, Notification notification)
        {
            return context.Notifications.AddAndSaveChanges(context, notification);
        }

        /// <summary>
        /// Deletes Notification by the notification id.
        /// </summary>        
        /// <param name="notificationID">Notification id.</param>
        /// <returns>True if notification deleted successfully else false.</returns>
        public static bool DeleteNotificationByID(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteNotificationByID(context, notificationID))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes Notification by the notification id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>True if notification deleted successfully else false.</returns>
        public static bool DeleteNotificationByID(ConfigDatabaseEntities context, int notificationID)
        {
            ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value p from Notifications as p Where p.NotificationID = @NotificationID"
                    , new ObjectParameter("NotificationID", notificationID));

            ObjectResult<Notification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (Notification notification in results)
            {
                context.Notifications.DeleteObject(notification);

                return true;
            }

            return false;
        }
        #endregion

        #region UTILITY USER ALLOWED NOTIFICATION RELATED METHODS
        /// <summary>
        /// Get Utility user allowed notifications.
        /// </summary>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetAllUtilityUserNotifications()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUserAllowedNotification> query
                    = context.CreateQuery<UtilityUserAllowedNotification>("Select value p from UtilityUserAllowedNotifications as p");
                ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Get Utility user allowed notifications by user Id.
        /// </summary>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetUtilityUserNotificationsByUtilityUserID(int utilityUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetUtilityUserNotificatiosnByUtilityUserID(context, utilityUserID);
            }
        }

        /// <summary>
        /// Get Utility user allowed notifications by user Id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user Id.</param>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetUtilityUserNotificatiosnByUtilityUserID(ConfigDatabaseEntities context, int utilityUserID)
        {
            ObjectQuery<UtilityUserAllowedNotification> query =
                    context.CreateQuery<UtilityUserAllowedNotification>(
                    "Select value p from UtilityUserAllowedNotifications as p Where p.UtilityUserID = @UtilityUserID"
                    , new ObjectParameter("UtilityUserID", utilityUserID));

            ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            return results.ToList();
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="utilityUserID">Utility user ID for which notification is to save.</param>
        /// <param name="notificationID">Notification ID.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(int utilityUserID, int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUserNotification(context, new UtilityUserAllowedNotification()
                {
                    ID = context.UtilityUserAllowedNotifications.NextId(f => f.ID),
                    UtilityUserID = utilityUserID,
                    NotificationID = notificationID,
                    Allowed = true,
                });
            }
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="utilityUserID">Utility user ID for which notification is to save.</param>
        /// <param name="notificationID">Notification ID.</param>
        /// <param name="allowed">True if sending the notification ID is allowed to send to utility user else false.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(int utilityUserID, int notificationID, bool allowed)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUserNotification(context, new UtilityUserAllowedNotification()
                {
                    ID = context.UtilityUserAllowedNotifications.NextId(f => f.ID),
                    UtilityUserID = utilityUserID,
                    NotificationID = notificationID,
                    Allowed = allowed,
                });
            }
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUserNotification">Utility user notification to save.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(ConfigDatabaseEntities context, UtilityUserAllowedNotification utilityUserNotification)
        {
            return context.UtilityUserAllowedNotifications.AddAndSaveChanges(context, utilityUserNotification);
        }

        /// <summary>
        /// Deletes the user's notification by the user Id.
        /// </summary>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>True if user's notification deleted successfully else false.</returns>
        public static bool DeleteUtilityUserNotificationsByUtilityUserID(int utilityUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteUtilityUserNotificationsByUtilityUserID(context, utilityUserID))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes the user's notification by the user Id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>True if user's notification deleted successfully else false.</returns>
        public static bool DeleteUtilityUserNotificationsByUtilityUserID(ConfigDatabaseEntities context, int utilityUserID)
        {
            ObjectQuery<UtilityUserAllowedNotification> query =
                    context.CreateQuery<UtilityUserAllowedNotification>(
                    "Select value p from UtilityUserAllowedNotifications as p Where p.UtilityUserID = @UtilityUserID"
                    , new ObjectParameter("UtilityUserID", utilityUserID));

            ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUserAllowedNotification utilityUserAllowedNotification in results)
            {
                context.UtilityUserAllowedNotifications.DeleteObject(utilityUserAllowedNotification);
            }

            return true;
        }
        #endregion

        #region SKELETON JOINT RELATED METHODS
        /// <summary>
        /// Gets the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="jointID">Joint id.</param>
        /// <returns>Skeleton Joint if found else will return null.</returns>
        public static SkeletonJoint GetSkeletonJointByID(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetSkeletonJointByID(context, jointID);
            }
        }

        /// <summary>
        /// Gets the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="jointID">Joint id.</param>
        /// <returns>Skeleton Joint if found else will return null.</returns>
        public static SkeletonJoint GetSkeletonJointByID(ConfigDatabaseEntities context, int jointID)
        {
            ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value p from SkeletonJoints as p Where p.JointID = @JointID"
                    , new ObjectParameter("JointID", jointID));

            ObjectResult<SkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (SkeletonJoint skeletonJoint in results) { return skeletonJoint; }

            return null;
        }

        /// <summary>
        /// Saves the Skeleton Joint to application database.
        /// </summary>
        /// <param name="jointID">Skeleton joint ID to save.</param>
        /// <returns>Saved skeleton joint object.</returns>
        public static SkeletonJoint SaveSkeletonJoint(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveSkeletonJoint(context, new SkeletonJoint()
                {
                    JointID = jointID
                });
            }
        }

        /// <summary>
        /// Saves the Skeleton Joint to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="skeletonJoint">SkeletonJoint to save.</param>
        /// <returns>Saved skeleton joint object.</returns>
        public static SkeletonJoint SaveSkeletonJoint(ConfigDatabaseEntities context, SkeletonJoint skeletonJoint)
        {
            return context.SkeletonJoints.AddAndSaveChanges(context, skeletonJoint);
        }

        /// <summary>
        /// Deletes the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="jointID">Joint id to delete.</param>
        /// <returns>True if skeleton deleted successfully else false.</returns>
        public static bool DeleteSkeletonJointByID(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteSkeletonJointByID(context, jointID))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Deletes the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="jointID">Joint id to delete.</param>
        /// <returns>True if skeleton deleted successfully else false.</returns>
        public static bool DeleteSkeletonJointByID(ConfigDatabaseEntities context, int jointID)
        {
            ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value p from SkeletonJoints as p Where p.JointID = @JointID"
                    , new ObjectParameter("JointID", jointID));

            ObjectResult<SkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (SkeletonJoint skeletonJoint in results)
            {
                context.SkeletonJoints.DeleteObject(skeletonJoint);
                return true;
            }

            return false;
        }
        #endregion

        #region DATA USER ALLOWED SKELETON JOINTS DATA RELATED METHODS
        /// <summary>
        /// Gets the service client allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>List of registered skeleton joints against provided data user ID.</returns>
        public static List<DataUserAllowedSkeletonJoint> GetDataUserAllowedSkeletonJointsByDataUserID(int dataUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetDataUserAllowedSkeletonJointsByDataUserID(context, dataUserID);
            }
        }

        /// <summary>
        /// Gets the service client allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>List of registered skeleton joints against provided data user ID.</returns>
        public static List<DataUserAllowedSkeletonJoint> GetDataUserAllowedSkeletonJointsByDataUserID(ConfigDatabaseEntities context, int dataUserID)
        {
            ObjectQuery<DataUserAllowedSkeletonJoint> query =
                    context.CreateQuery<DataUserAllowedSkeletonJoint>(
                    "Select value p from DataUserAllowedSkeletonJoints as p Where p.DataUserID = @DataUserID"
                    , new ObjectParameter("DataUserID", dataUserID));

            ObjectResult<DataUserAllowedSkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            return results.ToList();
        }

        /// <summary>
        /// Saves the allowed skeleton joints ID for provided data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <param name="jointID">Joint ID.</param>        
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(int dataUserID, int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUserAllowedSkeletonJoint(context, new DataUserAllowedSkeletonJoint()
                {
                    ID = context.DataUserAllowedSkeletonJoints.NextId(f => f.ID),
                    DataUserID = dataUserID,
                    JointID = jointID,
                    Allowed = true,
                });
            }
        }

        /// <summary>
        /// Saves the allowed skeleton joints ID for provided data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <param name="jointID">Joint ID.</param>
        /// <param name="allowed">True if data user can receive data of joint else flase.</param>
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(int dataUserID, int jointID, bool allowed)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUserAllowedSkeletonJoint(context, new DataUserAllowedSkeletonJoint()
                {
                    ID = context.DataUserAllowedSkeletonJoints.NextId(f => f.ID),
                    DataUserID = dataUserID,
                    JointID = jointID,
                    Allowed = allowed,
                });
            }
        }

        /// <summary>
        /// Saves the data user's allowed skeleton joints information to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserAllowedSkeletonJoint">Data user allowed skeleton joints instance to save.</param>
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(ConfigDatabaseEntities context, DataUserAllowedSkeletonJoint dataUserAllowedSkeletonJoint)
        {
            return context.DataUserAllowedSkeletonJoints.AddAndSaveChanges(context, dataUserAllowedSkeletonJoint);
        }

        /// <summary>
        /// Delete data user allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>True if data user's allowed skeleton joints deleted successfully else false.</returns>
        public static bool DeleteDataUserAllowedSkeletonJointsByDataUserID(int dataUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteDataUserAllowedSkeletonJointsByDataUserID(context, dataUserID))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Delete data user allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>True if data user's allowed skeleton joints deleted successfully else false.</returns>
        public static bool DeleteDataUserAllowedSkeletonJointsByDataUserID(ConfigDatabaseEntities context, int dataUserID)
        {
            ObjectQuery<DataUserAllowedSkeletonJoint> query =
                    context.CreateQuery<DataUserAllowedSkeletonJoint>(
                    "Select value p from DataUserAllowedSkeletonJoints as p Where p.DataUserID = @DataUserID"
                    , new ObjectParameter("DataUserID", dataUserID));

            ObjectResult<DataUserAllowedSkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUserAllowedSkeletonJoint dataUserAllowedSkeletonJoint in results)
            {
                context.DataUserAllowedSkeletonJoints.DeleteObject(dataUserAllowedSkeletonJoint);

            }

            return true;
        }
        #endregion

        #region SERVICE SETTINGS RELATED METHODS
        /// <summary>
        /// Gets service settings from application database
        /// </summary>
        /// <returns>List of service settings instances.</returns>
        public static List<ServiceSetting> GetServiceSettings()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<ServiceSetting> query
                    = context.CreateQuery<ServiceSetting>("Select value p from ServiceSettings as p");
                ObjectResult<ServiceSetting> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Saves service settings to application database.
        /// </summary>
        /// <param name="remotingServerPort">Remoting server port</param>
        /// <param name="remotingChannelName">Remoting channel name</param>
        /// <param name="webSocketServerIP">Web socket server ip</param>
        /// <param name="webSocketServerPort">Web socket server port</param>
        /// <param name="secureWebSocketServerIP">Secure web socket server ip</param>
        /// <param name="secureWebSocketServerPort">Secure web socket server port</param>
        /// <param name="runSecureSocketServer">Run secure web socket server</param>
        /// <param name="serverWebSocketCertificate">Web socket certificate path</param>
        /// <param name="logDirectory">Log directory</param>
        /// <param name="isLoggingEnabled">Logging enabled</param>
        /// <returns>Saved service setting object.</returns>
        public static ServiceSetting SaveServiceSettings(
            int remotingServerPort, String remotingChannelName, String webSocketServerIP, int webSocketServerPort, String secureWebSocketServerIP,
            int secureWebSocketServerPort, bool runSecureSocketServer, String serverWebSocketCertificate, String logDirectory, bool isLoggingEnabled)
        {
            DeleteServiceSettings();

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SavServiceSettings(context, new ServiceSetting()
                {
                    RemotingServerPort = remotingServerPort,
                    RemotingChannelName = remotingChannelName,
                    WebSocketServerIP = webSocketServerIP,
                    WebSocketServerPort = webSocketServerPort,
                    SecureWebSocketServerIP = secureWebSocketServerIP,
                    SecureWebSocketServerPort = secureWebSocketServerPort,
                    RunSecureSocketServer = runSecureSocketServer,
                    ServerWebScoketCertificate = serverWebSocketCertificate,
                    LogDirectory = logDirectory,
                    IsLoggingEnabled = isLoggingEnabled,
                    ID = context.ServiceSettings.NextId(f => f.ID),
                });
            }
        }

        /// <summary>
        /// Saves the service settings in the application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="serviceSettings">Service settings to be saved.</param>
        /// <returns>Saved service setting object.</returns>
        public static ServiceSetting SavServiceSettings(ConfigDatabaseEntities context, ServiceSetting serviceSettings)
        {
            return context.ServiceSettings.AddAndSaveChanges(context, serviceSettings);
        }

        /// <summary>
        /// Deletes service settings
        /// </summary>
        /// <returns>True if service settings deleted successfully else false.</returns>
        private static bool DeleteServiceSettings()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<ServiceSetting> query = context.CreateQuery<ServiceSetting>("Select value p from ServiceSettings as p");
                ObjectResult<ServiceSetting> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (ServiceSetting serviceSettings in results)
                {
                    context.ServiceSettings.DeleteObject(serviceSettings);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #endregion
    }
}